<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="rPi3l" id="rPi3l"><span data-lake-id="u73adc4d8" id="u73adc4d8">典型回答</span></h1>
  <p data-lake-id="ua810e76a" id="ua810e76a"><br></p>
  <p data-lake-id="ua602372a" id="ua602372a"><span data-lake-id="u92dffcd8" id="u92dffcd8">Redisson中定义了分布式延迟队列</span><strong><span data-lake-id="u71f03e54" id="u71f03e54">RDelayedQueue</span></strong><span data-lake-id="u4ce9013d" id="u4ce9013d">，这是一种基于我们前面介绍过的zset结构实现的延时队列，它允许以指定的延迟时长将元素放到目标队列中。</span></p>
  <p data-lake-id="u4870a58e" id="u4870a58e"><br></p>
  <p data-lake-id="uf3972d5b" id="uf3972d5b"><span data-lake-id="u3c04ce89" id="u3c04ce89">其实就是在zset的基础上增加了一个基于内存的延迟队列。当我们要添加一个数据到延迟队列的时候，redisson会把数据+超时时间放到zset中，并且起一个延时任务，当任务到期的时候，再去zset中把数据取出来，返回给客户端使用。</span></p>
  <p data-lake-id="ubf9118ac" id="ubf9118ac"><span data-lake-id="uaf537315" id="uaf537315">​</span><br></p>
  <pre lang="java"><code>
&lt;dependency&gt;
    &lt;groupId&gt;org.redisson&lt;/groupId&gt;
    &lt;artifactId&gt;redisson&lt;/artifactId&gt;
    &lt;version&gt;最新版&lt;/version&gt; 
&lt;/dependency&gt;
</code></pre>
  <p data-lake-id="u15bfbb2f" id="u15bfbb2f"><br></p>
  <p data-lake-id="ude3580c1" id="ude3580c1"><span data-lake-id="u6fe2a5a1" id="u6fe2a5a1">定义一个Redisson客户端：</span></p>
  <p data-lake-id="u866bed3c" id="u866bed3c"><span data-lake-id="u21ea9a74" id="u21ea9a74">​</span><br></p>
  <pre lang="java"><code>
 /**
 * @author Hollis
 */
@Configuration
public class RedissonConfig {
    
    @Bean(destroyMethod="shutdown")
    public RedissonClient redisson() throws IOException {
        Config config = new Config();
		config.useSingleServer().setAddress("redis://127.0.0.1:6379");
		RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

</code></pre>
  <p data-lake-id="u8e00d35b" id="u8e00d35b"><br></p>
  <p data-lake-id="u3b728bc2" id="u3b728bc2"><span data-lake-id="ud4c8418e" id="ud4c8418e">接下来，在想要使用延迟队列的地方做如下方式：</span></p>
  <p data-lake-id="u10af0f3b" id="u10af0f3b"><span data-lake-id="uaa62d50a" id="uaa62d50a">​</span><br></p>
  <p data-lake-id="ub350f02e" id="ub350f02e"><span data-lake-id="u3cc0f259" id="u3cc0f259">​</span><br></p>
  <pre lang="java"><code>
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

@Component
public class RedissonOrderDelayQueue {



    @Autowired
    RedissonClient redisson;

    public void addTaskToDelayQueue(String orderId) {
      
        RBlockingDeque&lt;String&gt; blockingDeque = redisson.getBlockingDeque("orderQueue");
        RDelayedQueue&lt;String&gt; delayedQueue = redisson.getDelayedQueue(blockingDeque);

        System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "添加任务到延时队列里面");
        delayedQueue.offer(orderId, 3, TimeUnit.SECONDS);
        delayedQueue.offer(orderId, 6, TimeUnit.SECONDS);
        delayedQueue.offer(orderId, 9, TimeUnit.SECONDS);
    }


   public String getOrderFromDelayQueue() {
        RBlockingDeque&lt;String&gt; blockingDeque = redisson.getBlockingDeque("orderQueue");
        RDelayedQueue&lt;String&gt; delayedQueue = redisson.getDelayedQueue(blockingDeque);
        String orderId = blockingDeque.take();
        return orderId;
    }

}

</code></pre>
  <p data-lake-id="u8dd46b94" id="u8dd46b94"><span data-lake-id="u85f4fec0" id="u85f4fec0">​</span><br></p>
  <p data-lake-id="uabd2728b" id="uabd2728b"><span data-lake-id="u87a15c0b" id="u87a15c0b">使用offer方法将两条延迟消息添加到RDelayedQueue中，使用take方法从RQueue中获取消息，如果没有消息可用，该方法会阻塞等待，直到消息到达。</span></p>
  <p data-lake-id="u4e800c8a" id="u4e800c8a"><span data-lake-id="uf012f21f" id="uf012f21f">​</span><br></p>
  <p data-lake-id="ucaa53fc2" id="ucaa53fc2"><br></p>
  <p data-lake-id="uf20e4a10" id="uf20e4a10"><span data-lake-id="uee430ec9" id="uee430ec9">我们使用 RDelayedQueue 的 offer 方法将元素添加到延迟队列，并指定延迟的时间。当元素的延迟时间到达时，Redisson 会将元素从 RDelayedQueue 转移到关联的 RBlockingDeque 中。</span></p>
  <p data-lake-id="u833a20b7" id="u833a20b7"><span data-lake-id="u936a6b60" id="u936a6b60">​</span><br></p>
  <p data-lake-id="u713ad507" id="u713ad507"><span data-lake-id="u0d3a39d3" id="u0d3a39d3">使用 RBlockingDeque 的 take 方法从关联的 RBlockingDeque 中获取元素。这是一个阻塞操作，如果没有元素可用，它会等待直到有元素可用。</span></p>
  <p data-lake-id="uc7ccf20c" id="uc7ccf20c"><span data-lake-id="u39ba8323" id="u39ba8323" class="lake-fontsize-12" style="color: rgb(55, 65, 81); background-color: rgb(247, 247, 248)">​</span><br></p>
  <p data-lake-id="u250cd960" id="u250cd960"><span data-lake-id="u71d385c1" id="u71d385c1">所以，为了从延迟队列中取出元素，使用 RBlockingDeque 的 take 方法，因为 Redisson 的 RDelayedQueue 实际上是通过转移元素到关联的 RBlockingDeque 来实现延迟队列的。</span></p>
 </body>
</html>